﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using popLib;
using popLib.ExtensionClass;
using PhotoMgr.src.database;
using PhotoMgr.src.common;
using System.IO;
using System.Threading;

namespace PhotoMgr.src.gui.photo
{
    public partial class HostForm2 : Form
    {
        SocketServer server;
        Contest contest;
        Round round;

        List<View_ContestUserSetting> settings;
        List<ClienList> clients;
        List<View_RoundImage> images;
        int SelectedRoundImageID = -1; //hinh dang duoc chon de xem tren cac may
        int SelectedRowIndex = -1;
        int ViewRoundImageID = -1; //hinh QSV dang xem
        int ViewRowIndex = -1;

        int DelayTime = 0;
        int CurrentTime = 0;
        int markCounter = 0;
        int totalClient = 0;
        bool isRoundCompleted = false;
        ScoreType CurrentScoreType;
        

        public HostForm2(int contestID, ScoreType scoretype)
        {
            InitializeComponent();

            this.Icon = PhotoMgr.Properties.Resources.logo32;

            clients = new List<ClienList>();
            images = new List<View_RoundImage>();
            settings = new List<View_ContestUserSetting>();
            CurrentScoreType = scoretype;

            dgv_user.AutoGenerateColumns = false;
            Global.InitDataGridView(dgv_user, new DataGridViewColumn[] {
                Global.GenColumn("Giám khảo", "Username").SetSizeMode(DataGridViewAutoSizeColumnMode.Fill),
                Global.GenColumn("Điểm", scoretype == ScoreType.MainScore ? "Score" : scoretype == ScoreType.SubScore ? "SubScore" : "ThirdScore" ),
                Global.GenColumn("IPAddress", "IPAddress").SetVisible(false),
                
            });

            dgv_image.AutoGenerateColumns = false;
            Global.InitDataGridView(dgv_image, new DataGridViewColumn[] { 
                Global.GenColumn("#", scoretype == ScoreType.MainScore ? "IsScore" : scoretype == ScoreType.SubScore ? "IsSubScore" : "IsThirdScore", Global.GenColumnType.CheckBox),
                Global.GenColumn("Hình ảnh", "ImageTitle").SetSizeMode(DataGridViewAutoSizeColumnMode.Fill),
                Global.GenColumn("Điểm", scoretype == ScoreType.MainScore ? "Score" : scoretype == ScoreType.SubScore ? "SubScore" : "ThirdScore"),
                Global.GenColumn(" ", "RoundImageID").SetVisible(false),
            });


            contest = DBManager.Detail_Contest(contestID);

            ReturnSet rs1 = DBManager.Contest_GetAvailableRound(contest.ContestID);
            if (rs1.Success)
            {
                round = (Round)rs1.Result;

                lbl_title.Text = contest.ContestName;
                this.Text = contest.ContestName + " - Vòng " + round.RoundLevel + "- [QSV:" + UserAccount.Instance.Fullname + "]";

                settings = DBManager.Contest_GetContestUserSetting(contest.ContestID);
                totalClient = settings.Where(x => x.RoleCode == 2).Count();
                CurrentTime = DelayTime = (int)settings[0].DelayTime;
            }
            else
            {
                FormLib.alert("Không tìm thấy vòng loại nào cho cuộc thi này!!");
                this.Opacity = 0;
                FormLib.ExitTimer(this, 100);
                return;
            }

            lbl_info.Text = string.Format("Người dùng: {0}({1})", UserAccount.Instance.Fullname, UserAccount.Instance.Username);

            server = new SocketServer(9889);
            server.WriteLog = false;
            server.ConnectionStatusChangedEvent += new ClientHandler.ConnectionStatusChanged(server_ConnectionStatusChangedEvent);
            server.ReceiveMessageEvent += new ClientHandler.ReceiveMessage(server_ReceiveMessageEvent);
        }

        private void HostForm2_Load(object sender, EventArgs e)
        {
            UpdateDisplay(false);
            if (server != null) server.Start();
            LockForm(true, "Xin vui lòng đợi tất cả các giám khảo kết nối tới máy chủ.");
        }

        void server_ReceiveMessageEvent(ClientHandler client, string message)
        {
            ThreadStart ts = delegate 
            {
                string[] items = message.Split(';');
                switch (items[0])
                {
                    case "LOGIN":
                        string username = items[1];
                        int userid = NumberLib.getInt(items[2]);

                        var rs = settings.Where(x => x.Username == username && x.RoleCode == 2);
                        var rs2 = clients.Where(x => x.IPAddress == client.Name);
                        var rs3 = clients.Where(x => x.Username == username || x.UserID == userid);

                        //check if correct user
                        if (rs.Count() == 1 && rs2.Count() == 1 && rs3.Count() == 0)
                        {
                            rs2.First().Username = username;
                            rs2.First().UserID = userid;
                            server.SendMessage(client.Name, string.Format("ACCEPTED;{0};{1};{2}", contest.ContestID, round.RoundID, Convert.ToInt16(CurrentScoreType) ));

                            //check if full user for this session -> start event                            
                            int totalConnectedClient = clients.Where(x => x.Username.Length > 0 && x.UserID > 0).Count();
                            if (totalClient == totalConnectedClient)
                            {
                                FormLib.hideLoading(this);
                                btn_start.Enabled = true;
                            }
                        }
                        else //else REJECT
                        {
                            server.SendMessage(client.Name, "REJECT");
                            server.clients.Remove(client.Name);
                            if (rs2.Count() > 0)
                            {
                                clients.Remove(rs2.First());
                            }
                        }

                        UpdateDisplay();

                        break;
                    case "UPDATE":

                        markCounter++;
                        if (markCounter >= totalClient && DBManager.ImageScore_IsScoreAll(SelectedRoundImageID, CurrentScoreType) )
                        {
                            btn_next.PerformClick();
                        }
                        else
                        {
                            UpdateDisplay();
                        }

                        break;
                }
            };
            if (this != null) this.Invoke(ts);
        }

        void server_ConnectionStatusChangedEvent(ClientHandler client, bool isConnected)
        {
            try
            {
                ThreadStart ts = delegate
                {
                    if (isConnected)
                    {
                        clients.Add(new ClienList() { IPAddress = client.Name, UserID = 0, Username = "", Score = 0 });
                        server.SendMessage(client.Name, "LOGIN");
                    }
                    else
                    {
                        var rs = clients.Where(x => x.IPAddress == client.Name);
                        if (rs.Count() > 0)
                        {
                            clients.Remove(rs.First());

                            if (!isRoundCompleted) LockForm(true, "Xin vui lòng đợi tất cả các giám khảo kết nối tới máy chủ.");
                        }
                    }

                    UpdateDisplay(false);
                };
                if (this != null)
                    this.Invoke(ts);
            }
            catch { }
        }

        void UpdateDisplay(bool autoNext = true)
        {
            if (round == null || contest == null) return;

            images = DBManager.Round_ListImage(round.RoundID, CurrentScoreType);


            //update list client and it's mark
            if (ViewRoundImageID > 0)
            {
                foreach (var item1 in clients)
                {
                    item1.Score = 0;
                }

                List<ImageScore> list = DBManager.ImageScore_ViewScore(ViewRoundImageID);

                foreach (var item in list)
                {
                    foreach (var item1 in clients)
                    {
                        if (item1.UserID == item.UserID)
                        {
                            item1.Score = item.Score != null ? (double)item.Score : 0;
                            item1.SubScore = item.SubScore != null ? (double)item.SubScore : 0;
                            item1.ThirdScore = item.ThirdScore != null ? (double)item.ThirdScore : 0;
                        }
                    }
                }
            }

            dgv_user.DataSource = null;
            dgv_user.DataSource = clients;

            dgv_image.DataSource = null;
            dgv_image.DataSource = images;

            for (int i = 0; i < dgv_image.Rows.Count; i++)
            {
                if (i == SelectedRowIndex)
                {
                    dgv_image.Rows[i].DefaultCellStyle.BackColor = Color.Red;
                }
                else if (i == ViewRowIndex)
                {
                    dgv_image.Rows[i].DefaultCellStyle.BackColor = Color.LightBlue;
                }
                else
                {
                    dgv_image.Rows[i].DefaultCellStyle.BackColor = Color.Empty;
                }
            }

            foreach (DataGridViewRow row in dgv_image.SelectedRows)
            {
                row.Selected = false;
            }

            if (SelectedRowIndex >= 0 && ViewRowIndex >= 0)
            {
                if (autoNext)
                {
                    dgv_image.Rows[SelectedRowIndex].Selected = true;
                    dgv_image.FirstDisplayedCell = dgv_image.Rows[SelectedRowIndex].Cells[1];
                }
                else
                {
                    dgv_image.Rows[ViewRowIndex].Selected = true;
                    dgv_image.FirstDisplayedCell = dgv_image.Rows[ViewRowIndex].Cells[1];
                }
            }

        }
                
        void DisplayImage(int roundImageID, int rowIndex, bool broatcastImage)
        {
            ViewRoundImageID = roundImageID;
            ViewRowIndex = rowIndex;

            //display image to form
            var rs = images.Where(x => x.RoundImageID == roundImageID);
            View_RoundImage img = rs.First();
            
            pbx_image.Image = System.Drawing.Image.FromFile(img.ImagePath);
            pbx_image.SizeMode = PictureBoxSizeMode.Zoom;
            lbl_imageTitle.Text = img.ImageTitle;
            lbl_artistName.Text = "Tác giả: " + img.ArtistName;
            lbl_note.Text = "";
            
            GC.Collect();

            //check if true -> broatcast
            if (broatcastImage)
            {
                server.SendMessageBroadcast(string.Format("VIEW;{0}", roundImageID));
                SelectedRoundImageID = roundImageID;
                SelectedRowIndex = rowIndex;
                startTimer();
                markCounter = 0;
            }

            UpdateDisplay(broatcastImage);
        }

        private void btn_start_Click(object sender, EventArgs e)
        {
            btn_start.Enabled = false;
            LockForm(false);
            btn_next.PerformClick();
        }

        private void btn_stop_Click(object sender, EventArgs e)
        {
            stopTimer();
            server.SendMessageBroadcast("END");
            server.Stop();
            
            btn_stop.Text = "Hoàn tất vòng thi\r\n(F7)";
            dgv_image.Enabled = pbx_image.Enabled = btn_next.Enabled = btn_pause.Enabled = btn_start.Enabled = false;
            isRoundCompleted = true;

            if (CurrentScoreType == ScoreType.MainScore)
            {
                FinishRoundForm finishform = new FinishRoundForm(contest.ContestID, round.RoundID);
                finishform.ShowDialog();
                if (finishform.DialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    this.Close();
                }
            }
            else
            {
                this.Close();
            }
        }

        private void btn_pause_Click(object sender, EventArgs e)
        {
            if (btn_pause.Text.StartsWith("Tạm"))
            {
                server.SendMessageBroadcast("PAUSE");
                btn_pause.Text = "Tiếp tục\r\n(F6)";
                btn_next.Enabled = btn_stop.Enabled = false;
                stopTimer(false);
            }
            else
            {
                server.SendMessageBroadcast("START");
                btn_pause.Text = "Tạm dừng\r\n(F6)";
                startTimer(false);
                btn_next.Enabled = btn_stop.Enabled = true;
            }
            
            
        }

        private void btn_next_Click(object sender, EventArgs e)
        {
            //kiem tra tu vi tri hien tai 
            bool isChecked = true;
            while (isChecked && SelectedRowIndex < images.Count - 1)
            {
                SelectedRowIndex++;
                isChecked = CurrentScoreType == ScoreType.MainScore ? (bool)images[SelectedRowIndex].IsScore : CurrentScoreType == ScoreType.SubScore ? (bool)images[SelectedRowIndex].IsSubScore : (bool)images[SelectedRowIndex].IsThirdScore;
                SelectedRoundImageID = images[SelectedRowIndex].RoundImageID;
            }

            if (!isChecked)
            {
                DisplayImage(SelectedRoundImageID, SelectedRowIndex, true);
                return;
            }

            //kiem tra lai tu dau
            SelectedRowIndex = -1;
            isChecked = true;
            while (isChecked && SelectedRowIndex < images.Count - 1)
            {
                SelectedRowIndex++;
                isChecked = CurrentScoreType == ScoreType.MainScore ? (bool)images[SelectedRowIndex].IsScore : CurrentScoreType == ScoreType.SubScore ? (bool)images[SelectedRowIndex].IsSubScore : (bool)images[SelectedRowIndex].IsThirdScore;
                SelectedRoundImageID = images[SelectedRowIndex].RoundImageID;
            }

            if (!isChecked)
            {
                DisplayImage(SelectedRoundImageID, SelectedRowIndex, true);
                return;
            }

            //kiem tra xem da het chua -> finish round
            int totalScored = images.Where(x => x.IsScore == true).Count();
            if (CurrentScoreType == ScoreType.SubScore)
                totalScored = images.Where(x => x.IsSubScore == true).Count();
            else if (CurrentScoreType == ScoreType.ThirdScore)
                totalScored = images.Where(x => x.IsThirdScore == true).Count();

            if (totalScored == images.Count)
            {
                if (FormLib.confirm("Tất cả hình ảnh đã được chấm đầy đủ.\r\nBạn có kết thúc vòng thi không?"))
                {
                    btn_stop_Click(null, new EventArgs());
                }
            }
        }

        private void dataGridView2_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            int roundImageID = NumberLib.getInt(dgv_image.Rows[e.RowIndex].Cells[3].Value);
            DisplayImage(roundImageID, e.RowIndex, false);
        }

        private void dataGridView2_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            int roundImageID = NumberLib.getInt(dgv_image.Rows[e.RowIndex].Cells[3].Value);
            DisplayImage(roundImageID, e.RowIndex, true);
        }

        private void dataGridView2_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {

        }

        void startTimer(bool isReset = true)
        {
            timer1.Start();
            if (isReset)
            {
                CurrentTime = DelayTime;
            }
        }

        void stopTimer(bool isReset = true)
        {
            timer1.Stop();
            if (isReset)
            {
                ts_progessbar.Value = 0;
                CurrentTime = DelayTime;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            CurrentTime--;
            ts_progessbar.Value = NumberLib.getInt(NumberLib.getDouble(CurrentTime) / (NumberLib.getDouble(DelayTime) / 100));

            if (CurrentTime <= 0)
            {
                stopTimer();
                btn_next.PerformClick();
            }
        }

        void LockForm(bool isLock = true, string message = "Xin vui lòng đợi!!!")
        {
            pbx_image.Enabled = dgv_image.Enabled = btn_pause.Enabled = btn_next.Enabled = btn_stop.Enabled = !isLock;

            if (isLock)
            {
                FormLib.showAnimatedLoading(this, message, false);
                stopTimer(false);
            }
            else
            {
                FormLib.hideLoading(this);
            }
        }

        private void HostForm2_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F5) btn_next.PerformClick();
            if (e.KeyCode == Keys.F6) btn_pause.PerformClick();
            if (e.KeyCode == Keys.F7) btn_stop.PerformClick();
            if (e.KeyCode == Keys.F8) btn_start.PerformClick();
        }

        private void HostForm2_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (server != null) server.Stop();
        }

    }

    public enum ScoreType:int { MainScore = 0, SubScore = 1, ThirdScore = 2 }

    class ClienList
    {
        public string Username { get; set; }
        public int UserID { get; set; }
        public string IPAddress { get; set; }
        public double Score { get; set; }
        public double SubScore { get; set; }
        public double ThirdScore { get; set; }
    }
}
